#ifndef FGE_DEMINAANIMATION_HPP
#define FGE_DEMINAANIMATION_HPP

#include <string>
#include <vector>
#include <utility>
#include <map>

#include "Animation.hpp"
#include "TextureDictionary.hpp"

namespace fge
{

class SpriteBatch;
class AssetManager;
class Texture;

struct Bone
{
	std::string Name;

	Vector2 Position;
	float Rotation;

	bool VerticalFlip;
	bool HorizontalFlip;

	int TextureIndex;
	int ParentIndex;

	bool Visible;
};

struct BoneTransform
{
	Vector2 Translation;
	float Rotation;
	Matrix3 Transform;
};

struct BoneTransitionState
{
	Vector2 Translation;
	float Rotation;
};

struct Keyframe
{
	std::vector<Bone> Bones;
	std::vector<Bone> UpdateOrderBones;

	bool VerticalFlip;
	bool HorizontalFlip;

	int FrameNumber;
	float FrameTime;

	std::string FrameTrigger;
};

class DeminaAnimation
{
public:
	DeminaAnimation(const std::string &filename, AssetManager *assetManager);
	~DeminaAnimation();

	static DeminaAnimation *FromFile(const std::string &filename);

	std::vector<Keyframe> keyframes;
	std::vector<Texture*> textures;

	int frameRate;
	int loopFrame;
	float loopTime;

protected:
	DeminaAnimation() : textureOwner(false) { }

	bool textureOwner;
};

class DeminaAnimationPlayer : public AnimationPlayer
{
public:
	DeminaAnimationPlayer();
	~DeminaAnimationPlayer();

	void AddAnimation(const std::string &name, DeminaAnimation *deminaAnimation);

	AnimationEvent Update(float deltaSeconds);
	AnimationEvent SetTime(float seconds);

	void Draw(SpriteBatch *spriteBatch, const Vector2 &position, float rotation = 0, const Vector2 &scale = Vector2::ONE, const Color &tintColor = Color::White, bool flipHorizontal = false, bool flipVertical = false);

	void StartAnimation(const std::string &name, bool allowRestart = false);
	void TransitionAnimation(const std::string &name, float transitionTime);

	bool IsTransitioning() const { return transitioning; }

protected:
	void InsertUpdateOrderIndex(int boneIndex);
	void UpdateBoneTransforms();

protected:
	std::map<std::string, DeminaAnimation*> animations;

	int boneCount;

	DeminaAnimation *currentAnimation;
	float currentAnimationTime;
	int currentKeyframeIndex;

	std::vector<BoneTransform> boneTransforms;
	std::vector<int> boneUpdateOrder;

	bool transitioning;
	DeminaAnimation *transitionAnimation;
	std::string transitionAnimationName;
	float transitionTime;
	float transitionTotalTime;
	std::vector<BoneTransitionState> transitionStates;
};

}

#endif//FGE_DEMINAANIMATION_HPP
